#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
const unsigned char Tab_ScrambleByte[24] = {171,55,105,56,188,163,8,63,86,110,210,113,121,70,16,126,172,221,164,226,242,140,32,253};
const unsigned char Table_Map[16]={'A','9','B','0','C','8','D','1','E','7','F','2','6','3','5','4'};//映射表
const unsigned char Table_index[16]={3,7,11,13,15,14,12,9,5,1,0,2,4,6,8,10};
unsigned char flash[12];//出厂时存储到flash中的sn号
//**************************************************************************************/
//输入：
//sn[12]:以SN号输入的12个字符，如"S21118000016"字符表示为 sn[12]={'S','2','1','1','1','8','0','0','0','0','1','6'}
//date:日期4字节的长整形，如20220410
//输出：
//code[32]：输出的32字节认证码，字符型
//**************************************************************************************/
void Encrypt_Encode(unsigned char sn[12], unsigned long date,unsigned char code[32])
{
    unsigned int i=0,j=0,t=0;
    unsigned char sn1[16]={0},scode[4]={0},temp=0,codebuf[32]={0};
    scode[0]=(unsigned char)(date>>24);
    scode[1]=(unsigned char)((date>>16)&0x00ff);
    scode[2]=(unsigned char)((date&0x0000ffff)>>8);
    scode[3]=(unsigned char)((date&0x0000ffff)&0x00ff);
    for(i=0;i<12;i++)
    {
        sn1[i]=(((sn[i]&0x0f)<<4)+(sn[i]>>4))^Tab_ScrambleByte[i];
    }
    for(i=0;i<4;i++)
    {
        sn1[i+12]=(((scode[i]&0x0f)<<4)+(scode[i]>>4))^Tab_ScrambleByte[i+12];
    }
    for(i=0;i<16;i++)
    {
        codebuf[i*2]=sn1[i]>>4;
        codebuf[i*2+1]=sn1[i]&0x0f;
    }
    for(i=0;i<32;i++)
    {
        if(i==3||i==7||i==11||i==15||i==19||i==23||i==27||i==31)
        {
            code[i]=codebuf[j+24];
            j++;
        }
        else
        {
            code[i]=codebuf[t];
            t++;
        }
        temp=code[i]^temp;
    }
    for(i=0;i<32;i++)
    {
        code[i]=Table_Map[code[i]^temp];
    }
}

//**************************************************************************************/
//输入：
//user_auth[32]:从用户获取的认证码，如"4E1AB964C36D7CD0D385F005A2F211C1"按字符输入'4','E','1'...
//local_sn[12]:存储在flash里的sn号，如"S21118000016"按字符输入'S','2','1'...
//输出：
//date:日期4字节的长整形，如20220410
//return：认证成功或失败标识，1：成功，0：失败
//**************************************************************************************/
unsigned char Encrypt_Decode(unsigned char local_sn[12],unsigned char user_auth[32],unsigned long *date)
{
    unsigned char i=0,k=0,temp=0;//j=0,t=0;
    unsigned char code[32]={0},codebuf1[24]={0},codebuf[8]={0};
	unsigned char auth_flag = 0;

    for(i=0;i<32;i++)
    {
        if(user_auth[i]>='0' && user_auth[i]<='9')
        {
            user_auth[i]=user_auth[i]-'0';
        }
        if(user_auth[i]>='A' && user_auth[i]<='F')
        {
            user_auth[i]=user_auth[i]-'A'+10;
        }
        code[i]=(unsigned char)Table_index[user_auth[i]];
        temp=code[i]^temp;
    }
    for(i=0;i<32;i++)
    {
        code[i]=code[i]^temp;
    }
    for(i=0;i<32;i++)
    {
        if(i==3||i==7||i==11||i==15||i==19||i==23||i==27||i==31)
        {
            codebuf[(i-3)/4]=code[i];
        }
        else
        {
            codebuf1[i-i/4]=code[i];
        }
    }
    for(i=0;i<12;i++)
    {
        codebuf1[i]=(codebuf1[i*2]<<4|codebuf1[i*2+1])^Tab_ScrambleByte[i];
        codebuf1[i]=((codebuf1[i]&0x0f)<<4)+(codebuf1[i]>>4);
    }
    for(i=0;i<12;i++)
    {
        if(codebuf1[i]==local_sn[i])
		{
			k++;
		}
    }
    if(k==12)
    {
		auth_flag = 1;
 //       printf("$auth ok\r\n");
    }
	else
    {
		auth_flag = 0;
		return auth_flag;
//        printf("$auth fail\r\n");
    }
    for(i=0;i<4;i++)
    {
        code[i]=(codebuf[i*2]<<4|codebuf[i*2+1])^Tab_ScrambleByte[i+12];
        code[i]=((code[i]&0x0f)<<4)+(code[i]>>4);
    }
    *date=(unsigned long)(code[0]<<24|code[1]<<16|code[2]<<8|code[3]);
    return auth_flag;
}